import { Book, BookList, Good, Chapter, Theme, Secret, Comment } from '../models';
import { formatBoolean, generateRandomNumberId } from '../utils/common';
import { getClassifyFormRegis } from '../bin/init';
import fs from 'fs';
import path from 'path';
import os from 'os';
import Queue from 'p-queue';
import uuid from 'uuid';

export default function (router) {
  /**
   * 小程序端获取书籍详情
   * @param {string} id 书籍id
   */
  router.get('/api/front/bookdetail', async ctx => {
    const userid = ctx.state.user ? ctx.state.user.userid : '';
    const id = ctx.request.query.id;
    if (!id) {
      ctx.body = { ok: false, msg: '缺少id参数' };
      return false;
    }
    const book = await Book.findById(id, '-source -create_time -secret');
    if (!book) {
      ctx.body = { ok: false, msg: '获取书籍详情失败' };
      return false;
    }

    // 是否将书籍加入了书架
    const isInList = formatBoolean(userid ? await BookList.findOne({ userid, 'books.bookid': id }, '_id') : false);
    // 是否订阅过该书籍
    const rss = formatBoolean(userid ? await BookList.findOne({ userid, 'books.bookid': id, 'books.rss': 1 }, '_id') : false);
    // 用户是否已经解锁过该书籍
    const unlocked = formatBoolean(userid ? await Secret.findOne({ userid, bookid: id, active: true }) : false);
    // 获取商品信息
    const good = await Good.getFormatInfo(id);

    ctx.body = {
      ok: true,
      msg: 'success',
      data: {
        ...book._doc,
        rss,
        good,
        unlocked,
        isInList
      }
    };
  });

  /**
   * 获取书籍分类列表的接口
   * @param {string} index 当前分类
   * @param {number} page 页数
   */
  router.get('/api/front/book/classify', async ctx => {
    let { page, classify = '' } = ctx.request.query;
    classify = classify.toString('utf8').trim();
    if (!page) {
      await ctx.json(false, '参数错误');
      return false;
    }

    const options = classify && classify != '全部书籍' ? { classify: { $in: classify } } : {};
    const total = await Book.countDocuments(options);
    const skipValue = (page - 1) * 10;
    let books = await Book.find(options, '_id name img_url author des')
      .sort({ hot_value: -1, create_time: -1 })
      .skip((page - 1) * 8)
      .limit(8);
    if (skipValue >= total) books = [];
    const classifys = await getClassifyFormRegis();
    await ctx.json(true, '获取书籍详情成功', {
      total,
      list: books || [],
      classify: ['', ...classifys]
    });
  });

  /**
   * 书籍无限滚动
   */
  router.get('/api/front/book/flow', async ctx => {
    const { page, limit } = ctx.parsePageAndLimit(ctx.request.query);
    const total = await Book.countDocuments();
    const result = await Book.find({}, '_id name author img_url des classify')
      .sort({ hot_value: -1, create_time: -1 })
      .skip((page - 1) * limit)
      .limit(limit);
    await ctx.json(true, 'success', { total, list: result || [] });
  });

  /**
   * 小程序搜索书籍接口
   * @param {string} keyword 关键字
   */
  router.post('/api/front/book/search', async ctx => {
    let { page, keyword } = ctx.request.body;
    keyword = keyword.toString('utf8').trim();
    if (!keyword) await ctx.json(false, '请输入正确的搜索关键字');
    const reg = new RegExp(keyword, 'i');
    const options = { $or: [{ name: reg }, { author: reg }] };
    const total = await Book.countDocuments(options);
    const result = await Book.find(options, '_id name author img_url des classify')
      .sort({ hot_value: -1, create_time: -1 })
      .skip((page - 1) * 8)
      .limit(8);
    await ctx.json(true, '搜索成功', { total, list: result || [] });
  });

  /**
   * 小程序获取搜索提示接口
   */
  router.post('/api/front/book/search_help', async ctx => {
    const keyword = ctx.request.body.keyword.toString('utf8').trim();
    if (keyword) {
      const reg = new RegExp(keyword, 'i');
      const result = await Book.find(
        {
          $or: [{ name: reg }, { author: reg }]
        },
        'name author'
      ).sort({ hot_value: -1, create_time: -1 });
      const nameArr = [];
      const authorArr = [];
      result.forEach(item => {
        if (item.name.match(reg)) {
          nameArr.push(item.name);
        }
        if (item.author.match(reg)) {
          authorArr.push(item.author);
        }
      });
      await ctx.json(true, '获取搜索提示成功', { list: nameArr.concat(authorArr) });
    } else {
      await ctx.json(false, '请输入正确的搜索关键字');
    }
  });

  /**
   * 后台搜索书籍
   * @param {string} keyword 关键字
   */
  router.get('/api/admin/book/search', async ctx => {
    const { keyword = '' } = ctx.request.query;
    let result = [];
    if (!keyword) {
      // 关键字为空就给出几本当前最热的书籍
      result = await Book.find({}, 'name author img_url des classify').sort({ hot_value: -1, create_time: -1 }).limit(5);
      await ctx.json(true, '搜索成功', { list: result });
      return;
    }
    const reg = new RegExp(keyword.toString('utf8').trim(), 'i');
    result = await Book.find({ $or: [{ name: reg }, { author: reg }] }, 'name author img_url des classify').sort({ hot_value: -1, create_time: -1 });
    await ctx.json(true, '搜索成功', { list: result });
  });

  /**
   * 后台获取所有书籍的列表
   */
  router.get('/api/admin/book/all', async ctx => {
    const allBooks = await Book.find({}, 'id name author');
    ctx.body = { ok: true, list: allBooks, msg: '获取书籍列表成功' };
  });

  /**
   * 后台获取所有不在商品中的书籍
   */
  router.get('/api/admin/book/sign_good', async ctx => {
    const allGoods = (await Good.find({}, 'bookid')) || [];
    const allBooks = await Book.find({ _id: { $nin: allGoods.map(item => item.bookid) } }, 'id name author');
    ctx.body = { ok: true, list: allBooks, msg: '获取书籍列表成功' };
  });

  /**
   * 后台书籍管理
   */
  router.get('/api/admin/book', async ctx => {
    let { page, limit, name, author, status, secret } = ctx.request.query;
    if (page) {
      page = parseInt(page);
    } else {
      page = 1;
    }
    if (limit) {
      limit = parseInt(limit);
    } else {
      limit = 10;
    }
    let condition = {};
    if (name) {
      condition.name = new RegExp(name, 'i');
    }
    if (author) {
      condition.author = new RegExp(author, 'i');
    }
    if (parseInt(status) === 1) {
      condition.update_status = '连载中';
    }
    if (secret) {
      condition.secret = secret;
    }
    const total = await Book.countDocuments(condition);
    const books = await Book.find(condition)
      .sort({ update_time: -1 })
      .skip((page - 1) * limit)
      .limit(limit);
    const classifys = await getClassifyFormRegis();
    ctx.body = {
      ok: true,
      total,
      list: books,
      msg: '获取书籍列表成功',
      classify: classifys
    };
  });

  /**
   * 后台书籍管理--添加书籍
   */
  router.post('/api/admin/book', async ctx => {
    let { name, img_url, author, des, classify, update_status, newest_chapter, total_words, hot_value, secret } = ctx.request.body;
    // format page and limit
    if (hot_value) {
      hot_value = parseInt(hot_value);
    } else {
      hot_value = 0;
    }
    if (newest_chapter) {
      newest_chapter = parseInt(newest_chapter);
    } else {
      newest_chapter = 0;
    }
    // query book
    let book = await Book.create({
      name: name,
      img_url: img_url,
      author: author,
      des: des,
      classify: classify,
      update_status: update_status,
      newest_chapter: newest_chapter,
      total_words: total_words,
      hot_value: hot_value,
      secret: secret || generateRandomNumberId(),
      update_time: new Date(),
      create_time: new Date()
    });
    if (book) {
      ctx.body = { ok: true, data: book, msg: '添加书籍成功' };
    } else {
      ctx.body = { ok: false, msg: '添加书籍失败' };
    }
  });

  /**
   * 后台书籍管理--更新书籍
   */
  router.patch('/api/admin/book/:id', async ctx => {
    let { name, img_url, author, des, classify, update_status, newest_chapter, total_words, hot_value, secret, source } = ctx.request.body;
    let id = ctx.params.id;
    let result = await Book.updateOne(
      { _id: id },
      {
        $set: {
          name: name,
          img_url: img_url,
          author: author,
          des: des,
          classify: classify,
          update_status: update_status,
          newest_chapter: newest_chapter,
          total_words: total_words,
          hot_value: hot_value,
          update_time: new Date(),
          secret,
          source
        }
      }
    );
    if (result.ok === 1) {
      let newest = await Book.findById(id);
      ctx.body = { ok: true, msg: '更新书籍成功', data: newest };
    } else {
      ctx.body = { ok: false, msg: '更新书籍失败', data: result };
    }
  });

  /**
   * 后台书籍管理--删除书籍
   */
  router.delete('/api/admin/book/:id', async ctx => {
    let id = ctx.params.id;
    let thisBook = await Book.findById(id);
    if (thisBook) {
      // 清除对应的章节
      await Chapter.deleteMany({ bookid: thisBook.id });
      // 清除对应的商品
      await Good.deleteMany({ bookid: thisBook.id });
      // 清除书籍对应的评论
      await Comment.deleteMany({ bookid: thisBook.id });
      // 清除书籍对应的秘钥
      await Secret.deleteMany({ bookid: thisBook.id });
      // 从主题中删除对应的书籍
      let allTheme = await Theme.find({}, 'books').populate({
        path: 'books',
        options: {
          sort: {
            index: 1
          }
        }
      });
      allTheme.forEach(async item => {
        const isCurrentBookInTheme = item.books.some(bookItem => {
          return bookItem.bookid.toString() === thisBook.id;
        });
        if (isCurrentBookInTheme) {
          let newBooks = [];
          let currentIndex = 0;
          item.books.forEach(bookItem => {
            if (bookItem.bookid.toString() !== thisBook.id) {
              bookItem.index = currentIndex;
              currentIndex++;
              newBooks.push(bookItem);
            }
          });
          await Theme.updateOne({ _id: item._id }, { $set: { books: newBooks } });
        }
      });
      // 移除书架存储的书
      await BookList.updateMany({ books: { $elemMatch: { bookid: thisBook.id } } }, { $pull: { books: { $elemMatch: { bookid: thisBook.id } } } });
      let result = await Book.deleteOne({ _id: id });
      if (result.ok === 1) {
        ctx.body = { ok: true, msg: '删除成功' };
      } else {
        ctx.body = { ok: false, msg: '删除失败', data: result.result };
      }
    } else {
      ctx.body = { ok: false, msg: '删除失败，找不到此书籍' };
    }
  });

  /**
   * 后台书籍管理--下载书籍为txt
   */
  router.get('/api/admin/book/:id/generate_txt', async ctx => {
    const bookId = ctx.params.id;
    // 获取书籍信息
    const thisBook = await Book.findById(bookId);
    if (!thisBook) {
      ctx.body = { ok: false, msg: '书籍不存在' };
      return;
    }
    // 获取书籍的所有章节
    const chapters = await Chapter.find({ bookid: bookId });
    // 创建一个临时的txt文件
    const tmpdir = fs.mkdtempSync(path.join(os.tmpdir(), `./${uuid.v1()}`));
    const filePath = path.join(tmpdir, `${thisBook.name}.txt`);
    fs.appendFileSync(filePath, `书籍信息:\n书籍名称: ${thisBook.name}\n作者: ${thisBook.author}\n简介: ${thisBook.des}\n更新状态: ${thisBook.update_status}\n最新更新时间: ${thisBook.update_time}\n`);

    return new Promise(resolve => {
      const queue = new Queue({ concurrency: 1, autoStart: false });
      chapters.forEach(item => {
        queue.add(() => {
          // 暂停10s
          fs.appendFileSync(filePath, `\n第${item.num}章 ${item.name}\n\n${item.content}\n`);
        });
      });
      queue.start();
      queue.onIdle().then(() => {
        resolve(true);
        ctx.body = { ok: true, msg: '生成txt成功', url: encodeURI(filePath) };
      });
    });
  });

  /**
   * 手动更新书籍
   */
  router.get('/api/admin/update_book', async ctx => {
    ctx.body = { ok: true, msg: '脚本被删除', data: {} };
  });
}
